package com.allwees.bs.c.common.aop.exception;

import com.allwees.bs.core.modelbase.constant.ErrorMessage;
import com.allwees.bs.core.modelbase.constant.ErrorMessageMap;
import com.allwees.bs.core.modelbase.constant.ResultCode;
import com.allwees.bs.core.modelbase.vo.R;
import com.allwees.core.common.exception.BaseException;
import com.allwees.core.common.i18n.MessageSourceUtil;
import com.allwees.core.common.util.http.RequestContext;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Profile;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

@Profile("test")
@Slf4j
@RestControllerAdvice
public class TestExceptionHandler {

    @ExceptionHandler(Exception.class)
    public R handleException(Exception e) {
        log.error("===>Unkown Exception:{}", e.getMessage(), e);
        return R.error(MessageSourceUtil.getMessageOrDefault(e.getMessage(), e.getMessage()));
    }

    @ExceptionHandler(BaseException.class)
    public R formatErrorHandler(BaseException e) {
        log.error("===>BaseException:{}", e.getMessage(), e);
        return R.error(e.getCode(), MessageSourceUtil.getMessageOrDefault(
                "result.code.(" + ErrorMessageMap.get(e.getMsg()) + ")", e.getMsg()));
    }

    @ExceptionHandler(NoHandlerFoundException.class)
    public R noHandlerFoundException(NoHandlerFoundException e) {
        log.error("===>NoHandlerFoundException:{}", e.getMessage(), e);
        return R.error(HttpStatus.NOT_FOUND.value(),
                MessageSourceUtil.getMessage("http." + HttpStatus.NOT_FOUND.value()));
    }

    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    public R MethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        log.error("===>RequestMethodNotSupportedException:{}", e.getMessage(), e);
        return R.error(HttpStatus.METHOD_NOT_ALLOWED.value(),
                MessageSourceUtil.getMessage("http." + HttpStatus.METHOD_NOT_ALLOWED.value()));
    }

    @ExceptionHandler({MethodArgumentNotValidException.class})
    public R formatErrorHandler(MethodArgumentNotValidException e) {
        List<String> errors = Lists.newArrayList();
        if (e.getBindingResult().hasErrors()) {
            for (FieldError fieldError : e.getBindingResult().getFieldErrors()) {
                errors.add(fieldError.getField() + ":" + fieldError.getDefaultMessage());
            }
        }
        log.error("===> MethodArgumentNotValidException: [msg={},request:{}]", StringUtils.join(errors, ","), RequestContext.getContext(), e);
        return R.error(ResultCode.PARAM_ERROR, StringUtils.join(errors, "\n"));
    }

    @ExceptionHandler({ConstraintViolationException.class})
    public R formatErrorHandler(ConstraintViolationException e) {
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        Iterator<ConstraintViolation<?>> iterator = constraintViolations.iterator();
        List<String> errors = Lists.newArrayList();
        while (iterator.hasNext()) {
            ConstraintViolation<?> cvl = iterator.next();
            errors.add(cvl.getMessage());
        }
        String msg = StringUtils.join(errors, ",");
        log.error("===> ConstraintViolationException: [msg={},request:{}]", msg, RequestContext.getContext(), e);
        return R.error(ResultCode.PARAM_ERROR, ErrorMessage.PARAM_ERROR);
    }

    @ExceptionHandler({HttpMessageNotReadableException.class})
    public R formatErrorHandler(HttpMessageNotReadableException e) {
        String message = e.getMessage();
        log.error("===> HttpMessageNotReadableException: [msg={},request:{}]", message, RequestContext.getContext(), e);
        return R.error(ResultCode.PARAM_ERROR, ErrorMessage.PARAM_ERROR);
    }
}
